iT邦幫忙

2024 iThome 鐵人賽

DAY 6
0

Day27 要來做個可以左右拖曳的目錄

資料

const items: number[] = Array.from({ length: 25 }, (_, i) => i + 1);

const getBackgroundColor = (index: number): string => {
  const colors: string[] = [
    "bg-[dodgerblue]",
    "bg-[goldenrod]",
    "bg-[paleturquoise]",
    "bg-[gold]",
    "bg-[cadetblue]",
    "bg-[tomato]",
    "bg-[lightcoral]",
    "bg-[darkslateblue]",
    "bg-[rebeccapurple]",
  ];

  return colors[index % 9];
};
  const [isDown, setIsDown] = useState<boolean>(false);
  const [startX, setStartX] = useState<number>(0);
  const [scrollLeft, setScrollLeft] = useState<number>(0);
  const sliderRef = useRef<HTMLDivElement | null>(null);

滑鼠動作


  const handleMouseDown = (e: MouseEvent<HTMLDivElement>) => {
    if (sliderRef.current) {
      setIsDown(true);
      setStartX(e.pageX - sliderRef.current.offsetLeft);
      setScrollLeft(sliderRef.current.scrollLeft);
    }
  };

  const handleMouseLeave = () => {
    setIsDown(false);
  };

  const handleMouseUp = () => {
    setIsDown(false);
  };

  const handleMouseMove = (e: MouseEvent<HTMLDivElement>) => {
    if (!isDown || !sliderRef.current) {
      return;
    }
    e.preventDefault();
    const x = e.pageX - sliderRef.current.offsetLeft;
    const walk = (x - startX) * 3;
    sliderRef.current.scrollLeft = scrollLeft - walk;
  };

畫面結構


  return (
    <div className="min-h-screen flex justify-center items-center bg-cover bg-fixed bg-[url('https://source.unsplash.com/NFs6dRTBgaM/2000x2000')] font-sans text-xl m-0">
      <div
        ref={sliderRef}
        className={`h-[700px] p-[100px] w-full border border-white overflow-x-scroll overflow-y-hidden whitespace-nowrap select-none cursor-pointer transition-all duration-200 will-change-transform relative bg-white/10 text-[0px] ${
          isDown ? "bg-white/30 cursor-grabbing" : ""
        }`}
        style={{
          transform: `scale(${isDown ? 1 : 0.98})`,
          perspective: "500px",
        }}
        onMouseDown={handleMouseDown}
        onMouseLeave={handleMouseLeave}
        onMouseUp={handleMouseUp}
        onMouseMove={handleMouseMove}
      >
        {items.map((item, index) => (
          <div
            key={item}
            className={`w-[200px] h-[calc(100%-40px)] inline-flex items-center justify-center text-[80px] font-thin text-black/15 ${getBackgroundColor(
              index
            )}`}
            style={{
              boxShadow: "inset 0 0 0 10px rgba(0,0,0,0.15)",
              transform: `scaleX(1.31) rotateY(${
                index % 2 === 0 ? 40 : -40
              }deg)`,
            }}
          >
            {item.toString().padStart(2, "0")}
          </div>
        ))}
      </div>
    </div>
  );

DEMO

https://codesandbox.io/p/devbox/2vm88y


上一篇
[Day26]_Stripe-Follow-Along-Nav
下一篇
[Day28]_Video-Speed-Controller
系列文
React30——用 React 探索 JavaScript30 的魅力30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言